/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.etrs.formathlon.vue.jsf.form.user.suivi_formation.attestation;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
import net.etrs.formathlon.entity.formation.Domaine;
import net.etrs.formathlon.control.exception.ExceptionManager;
import net.etrs.formathlon.entity.formation.Formation;
import net.etrs.formathlon.entity.utilisateur.Personnel;
import net.etrs.formathlon.entity.utilisateur.Utilisateur;
import net.etrs.formathlon.metier.exception.MetierException;
import net.etrs.formathlon.metier.service.EntiteManager;
import net.etrs.formathlon.metier.service.EntiteManager.NiveauHierarchique;
import net.etrs.formathlon.persistance.formation.DomaineFacade;
import net.etrs.formathlon.persistance.formation.ParticipationFacade;
import net.etrs.formathlon.persistance.utilisateur.UtilisateurFacade;
import net.etrs.formathlon.vue.jsf.utils.GeneralBean;
import net.etrs.formathlon.vue.jsf.utils.Transformer;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

/**
 * Permet de voir les formation d'une personne et d'imprimer l'attestation.
 * @author OPIF
 */
@ManagedBean
@ViewScoped
public class ParcoursPedaBean extends GeneralBean {

    @EJB
    private DomaineFacade domaineFacade;
    @EJB
    private ParticipationFacade participationFacade;
    @EJB
    private UtilisateurFacade utilisateurFacade;
    private Utilisateur utilisateur;
    private List<SelectItem> listItemSubordonne = new ArrayList<SelectItem>();
    private Set<String> listDiv = new HashSet<String>();
    private String division = "Tous";
    private Set<String> listCours = new HashSet<String>();
    private String cours = "Tous";
    private Personnel personnel;
    private List<Utilisateur> listPersonnelSub = new ArrayList<Utilisateur>();
    private List<Personnel> listPersonnelAff = new ArrayList<Personnel>();
    private List<InfoParticipation> tableauParcours = new ArrayList<InfoParticipation>();
    // Période à laquelle le formateur a été présent (utile pour imprimer l'attestation)
    private Personnel personnelPdf;
    private Date dateDebut;
    private Date dateFin;

    /**
     * Methode d'initialisation.
     */
    @PostConstruct
    public void init() {
        try {
            utilisateur = getLoginControler().getUtilisateurConnecte();
            //on init en mettant l'utilisateur dans personnel
            Personnel pers = utilisateur.getPersonnel();
            listPersonnelAff.clear();
            //si c'est un chef
            if (getLoginControler().isChef() || getLoginControler().isGestionnaire()) {
                //peu importe de quoi il est chef on récupère ses personnels subordonnés 
                //(sous forme d'utilisateur)
                if (getLoginControler().isGestionnaire()) {
                    listPersonnelSub = utilisateurFacade.getSubordonnes(utilisateur.getEntite(), NiveauHierarchique.ETRS);
                } else {
                    listPersonnelSub = utilisateurFacade.getSubordonnes(utilisateur);
                }
                //on crée un selectItem pour les personnels
                listItemSubordonne.clear();
                //on cree la liste des cours pour le chef de div
                if (getLoginControler().isChefDivision()) {
                    //c'est un chef de div
                    division = EntiteManager.getSubEntite(utilisateur.getEntite(), NiveauHierarchique.DIVISION);
                    listCours = utilisateurFacade.getDistinctCours(EntiteManager.getSubEntite(utilisateur.getEntite(), NiveauHierarchique.DIVISION));
                }

                for (Utilisateur util : listPersonnelSub) {
                    pers = util.getPersonnel();
                    //chef de cours on cree la selectItem
                    if (getLoginControler().isChefCours()) {
                        division = EntiteManager.getSubEntite(utilisateur.getEntite(), NiveauHierarchique.DIVISION);
                        cours = EntiteManager.getSubEntite(utilisateur.getEntite(), NiveauHierarchique.COURS);
                        listItemSubordonne.add(new SelectItem(pers, Transformer.formatPersonnelGradePrenomNom(pers)));
                    }
                    //par défaut on affiche tous les personnels
                    listPersonnelAff.add(pers);
                }
            } else {
                //pas de chef c'est donc un formateur
                listPersonnelAff.add(pers);
            }
        } catch (MetierException ex) {
            Logger.getLogger(ParcoursPedaBean.class.getCanonicalName()).log(Level.SEVERE, null, ex);
        }
        constructionTableau();
    }

    /**
     * Methode appeler pour un changement div.
     */
    public void changeDiv() {
        if (division.equals("Tous")) {
            //initialisation complete
            init();
        } else {
            cours = "Tous";
            listItemSubordonne.clear();
            personnel = null;
            changeList();
        }
    }

    /**
     * Au changement de la liste des cours.
     */
    public void changeCours() {
        personnel = null;
        changeList();
    }

    /**
     * Utilisation des filtres.
     */
    public void changeList() {
        try {
            Personnel pers;
            String entite = division;
            String entiteSubordonne = "";
            //initialisation des listes avant de les modifier
            listPersonnelAff.clear();
            listCours = utilisateurFacade.getDistinctCours(division);
            //une division est choisi
            if (!cours.equals("Tous")) {
                entite = String.format("%s/%s", division, cours);
                //un cours est choisi, on met a jour le selectItem
                listItemSubordonne.clear();
            }

            for (Utilisateur util : listPersonnelSub) {
                pers = util.getPersonnel();
                entiteSubordonne = EntiteManager.getEntite(util.getEntite(),
                        NiveauHierarchique.DIVISION, NiveauHierarchique.COURS);

                //un cours est choisi on cree la selectItem si la personne convient
                if (!cours.equals("Tous")) {
                    if (entite.equals(entiteSubordonne)) {
                        listItemSubordonne.add(new SelectItem(pers, Transformer.formatPersonnelGradePrenomNom(pers)));
                    }
                } else {
                    //tous les cours
                    entiteSubordonne = EntiteManager.getSubEntite(util.getEntite(), NiveauHierarchique.DIVISION);
                }
                if (entite.equals(entiteSubordonne)) {
                    listPersonnelAff.add(pers);
                }
            }
        } catch (MetierException ex) {
            Logger.getLogger(ParcoursPedaBean.class.getCanonicalName()).log(Level.SEVERE, null, ex);
        }
        if (!cours.equals("Tous") && personnel != null) {
            listPersonnelAff.clear();
            listPersonnelAff.add(personnel);
        }
        constructionTableau();
    }

    /**
     * Methode utilisé pour la construction du tableau.
     */
    private void constructionTableau() {
        tableauParcours.clear();
        for (Personnel pers : listPersonnelAff) {
            List<String> tableauParticipation = new ArrayList<String>();
            for (Domaine domaine : getListDomaine()) {
                for (Formation formation : domaine.getListFormation()) {
                    tableauParticipation.add(participationFacade.aEueLieu(pers, formation));
                }
            }
            tableauParcours.add(new InfoParticipation(pers, tableauParticipation));
        }
    }

    /**
     * Validation de la demande de téléchargement de la version PDF.
     * Génération du document et livraison sous forme de flux.
     * @return Le flux du document PDF.
     */
    public StreamedContent getAttestation() {
        try {
            getPopupBean().close();
            InputStream stream = participationFacade.getAttestation(personnelPdf.getUtilisateur(), dateDebut, dateFin);
            displayMessage("Création réussie.");
            return new DefaultStreamedContent(stream, "application/pdf", "attestation.pdf");
        } catch (Exception ex) {
            displayErreur(ExceptionManager.traiter(ex));
            return null;
        }
    }

    /**
     * Clic sur le lien 'Version PDF' : ouverture de la popup pour renseigner les dates.
     */
    public void demanderAttestation(Personnel personnel) {
        personnelPdf = personnel;
        getPopupBean().open("Période d'affectation");
    }

    /**
     * Annulation de la demande de PDF.
     */
    public void annuler() {
    }

    /**
     * @return the listItemSubordonne
     */
    public List<SelectItem> getListItemSubordonne() {
        return listItemSubordonne;
    }

    /**
     * @return the utilisateur
     */
    public Utilisateur getUtilisateur() {
        return utilisateur;
    }

    /**
     * @param utilisateur the utilisateur to set
     */
    public void setUtilisateur(Utilisateur utilisateur) {
        this.utilisateur = utilisateur;
    }

    /**
     * @return the dateDebut
     */
    public Date getDateDebut() {
        return dateDebut;
    }

    /**
     * @param dateDebut the dateDebut to set
     */
    public void setDateDebut(Date dateDebut) {
        this.dateDebut = dateDebut;
    }

    /**
     * @return the dateFin
     */
    public Date getDateFin() {
        return dateFin;
    }

    /**
     * @param dateFin the dateFin to set
     */
    public void setDateFin(Date dateFin) {
        this.dateFin = dateFin;
    }

    /**
     * @return the listCours
     */
    public Set<String> getListCours() {
        return listCours;
    }

    /**
     * @return the listDiv
     */
    public Set<String> getListDiv() {
        try {
            return utilisateurFacade.getDistinctDivision();
        } catch (MetierException ex) {
            Logger.getLogger(ParcoursPedaBean.class.getCanonicalName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    /**
     * @return the division
     */
    public String getDivision() {
        return division;
    }

    /**
     * @param division the division to set
     */
    public void setDivision(String division) {
        this.division = division;
    }

    /**
     * @return the cours
     */
    public String getCours() {
        return cours;
    }

    /**
     * @param cours the cours to set
     */
    public void setCours(String cours) {
        this.cours = cours;
    }

    /**
     * 
     * @return la liste des domaines
     */
    public List<Domaine> getListDomaine() {
        return domaineFacade.getDomaineWithFormation();
    }

    /**
     * 
     * @return le personnel en cours
     */
    public Personnel getPersonnel() {
        return personnel;
    }

    /**
     * 
     * @param personnel 
     */
    public void setPersonnel(Personnel personnel) {
        this.personnel = personnel;
    }

    /**
     * 
     * @return liste des infoParticipation
     */
    public List<InfoParticipation> getTableauParcours() {
        return tableauParcours;
    }

    /**
     * Classe pour les informations sur les participations dans le cadre 
     * d'un parcours pédagogique.
     */
    public class InfoParticipation {

        private Personnel perso;
        private List<String> infos;

        public InfoParticipation(Personnel perso, List<String> infos) {
            this.perso = perso;
            this.infos = infos;
        }

        /**
         * @return the infos
         */
        public List<String> getInfos() {
            return infos;
        }

        /**
         * @param infos the infos to set
         */
        public void setInfos(List<String> infos) {
            this.infos = infos;
        }

        /**
         * @return the perso
         */
        public Personnel getPerso() {
            return perso;
        }

        /**
         * @param perso the perso to set
         */
        public void setPerso(Personnel perso) {
            this.perso = perso;
        }
    }
}
